﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;

namespace MasterListCreator.Classes
{
    static class Utility
    {
        public static string[] DirectoryListing(string path)
        {
            if (System.IO.Directory.Exists(path))
            {
                return System.IO.Directory.GetFiles(path, "*.*", System.IO.SearchOption.AllDirectories);
            }

            return null;
        }

        public static string[] GetDirectory(string path)
        {
            if (System.IO.Directory.Exists(path))
            {
                return System.IO.Directory.GetDirectories(path);
            }

            return null;
        }

        public static string[] GetFile(string path)
        {
            if (System.IO.Directory.Exists(path))
            {
                return System.IO.Directory.GetFiles(path);
            }

            return null;
        }

        /// <summary>
        /// Returns true if the given file path is a folder.
        /// </summary>
        /// <param name="Path">File path</param>
        /// <returns>True if a folder</returns>
        public static bool IsFolder(string path)
        {
            return ((System.IO.File.GetAttributes(path) & System.IO.FileAttributes.Directory) == System.IO.FileAttributes.Directory);
        }

        /// <summary>
        /// Gets Name of Folder or File.
        /// </summary>
        /// <param name="path">Path to get Folder or File.</param>
        /// <returns>FileName or Folder.</returns>
        public static string GetName(string path)
        {
            if (!System.IO.Directory.Exists(path) && !System.IO.File.Exists(path))
            {
                return string.Empty;
            }
                                    
            return System.IO.Path.GetFileName(path);                     
        }

        public static void WriteToTextFile(string path, string content)
        {
            using (System.IO.StreamWriter file = new System.IO.StreamWriter(path))
            {
                file.WriteLine(content);
            }
        }

        public static int GetPathLevel(string rootPath, string currentPath)
        {
            if (!System.IO.Directory.Exists(rootPath) || System.IO.Directory.Exists(currentPath))
            {
                return -1;
            }

            return rootPath.Split('\\').Length - currentPath.Split('\\').Length;
        }

        public static int GetMaxDirectoryLevel(string path)
        {
            return 0;
        }        

        /// <summary>
        /// Checks if Directory has sub directory or not.
        /// </summary>
        /// <param name="path">The directory to check.</param>
        /// <returns>Returs true if the directory has sub directorty, otherwise returns false.</returns>
        public static bool HasSubDirectory(string path)
        {
            if (!System.IO.Directory.Exists(path))
            {
                return false;
            }

            return System.IO.Directory.GetDirectories(path).Length > 0;
        }

        /// <summary>
        /// Check if Directory contains file or not.
        /// </summary>
        /// <param name="path">The directory to check.</param>
        /// <returns>Returns true if Directory has no File, otherwise return false.</returns>
        public static bool HasFile(string path)
        {
            if (!System.IO.Directory.Exists(path))
            {
                return false;
            }

            return System.IO.Directory.GetFiles(path).Length == 0;
        }

        /// <summary>
        /// Check if Directory is empty or not.
        /// </summary>
        /// <param name="path">The directory to check.</param>
        /// <returns>Returns true if Directory has no file and folder, otherwise returns false.</returns>
        public static bool IsEmpty(string path)
        {
            return (!HasFile(path) && !HasSubDirectory(path));
        }
        
        /// <summary>
        /// Converts List to DataTable.
        /// </summary>
        /// <typeparam name="T">Type of List.</typeparam>
        /// <param name="data">List to convert.</param>
        /// <returns>DataTable.</returns>
        public static System.Data.DataTable ToDataTable<T>(this IList<T> data)
        {
            PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(typeof(T));
            System.Data.DataTable table = new System.Data.DataTable();

            foreach (PropertyDescriptor prop in properties)
            {
                table.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
            }

            foreach (T item in data)
            {
                System.Data.DataRow row = table.NewRow();
                foreach (PropertyDescriptor prop in properties)
                {
                    row[prop.Name] = prop.GetValue(item) ?? DBNull.Value;
                }

                table.Rows.Add(row);
            }

            return table;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static DateTime GetLastModified(string path)
        {           
            if (IsFolder(path))
            {
                if (!Directory.Exists(path))
                {
                    return DateTime.MinValue;
                }

                FileInfo info = new FileInfo(path);
                return info.CreationTime;
            }
            else
            {
                if (!File.Exists(path))
                {
                    return DateTime.MinValue;
                }

                DirectoryInfo info = new DirectoryInfo(path);
                return info.CreationTime;
            }       
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static DateTime GetCreatedDateTime(string path)
        {            
            if (IsFolder(path))
            {
                if (!File.Exists(path))
                {
                    return DateTime.MinValue;
                }

                FileInfo info = new FileInfo(path);
                return info.CreationTime;
            }
            else
            {
                if (!Directory.Exists(path))
                {
                    return DateTime.MinValue;
                }

                DirectoryInfo info = new DirectoryInfo(path);
                return info.CreationTime;
            }            
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static DateTime GetLastAccessTimeDateTime(string path)
        {            
            if (IsFolder(path))
            {
                if (!Directory.Exists(path))
                {
                    return DateTime.MinValue;
                }

                FileInfo info = new FileInfo(path);
                return info.LastAccessTime;
            }
            else
            {
                if (!File.Exists(path))
                {
                    return DateTime.MinValue;
                }

                DirectoryInfo info = new DirectoryInfo(path);
                return info.LastAccessTime;
            }
        }

        public static long GetSizeOfPath(string path)
        {            
            if (IsFolder(path))
            {
                return 0;                
            }
            else
            {
                return new FileInfo(path).Length;                
            }
        }
          
        /// <summary>
        /// Returns the human-readable file size for an arbitrary, 64-bit file size
        /// The default format is "0.### XB", e.g. "4.2 KB" or "1.434 GB"
        /// </summary>
        /// <param name="i"></param>
        /// <returns></returns>
        public static string GetSizeReadable(long i)
        {
            string sign = (i < 0 ? "-" : "");
            double readable = (i < 0 ? -i : i);
            string suffix;
            if (i >= 0x1000000000000000) // Exabyte
            {
                suffix = "EB";
                readable = (double)(i >> 50);
            }
            else if (i >= 0x4000000000000) // Petabyte
            {
                suffix = "PB";
                readable = (double)(i >> 40);
            }
            else if (i >= 0x10000000000) // Terabyte
            {
                suffix = "TB";
                readable = (double)(i >> 30);
            }
            else if (i >= 0x40000000) // Gigabyte
            {
                suffix = "GB";
                readable = (double)(i >> 20);
            }
            else if (i >= 0x100000) // Megabyte
            {
                suffix = "MB";
                readable = (double)(i >> 10);
            }
            else if (i >= 0x400) // Kilobyte
            {
                suffix = "KB";
                readable = (double)i;
            }
            else
            {
                return i.ToString(sign + "0 B"); // Byte
            }
            readable = readable / 1024;

            return sign + readable.ToString("0.### ") + suffix;
        }
    }
}
